#include "weathertrayicon.h"
#include <QIcon>
#include <QTimer>
#include <QSettings>
#include <QVariant>
#include <QApplication>
#include <QDebug>
#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include <QRegExp>
#include <QTextDocumentFragment>
#include <QByteArray>
#include <QPixmap>

//https://tianqiapi.com/api.php?city=北京

WeatherTrayIcon::WeatherTrayIcon()
    :QSystemTrayIcon(), retryDelaySec(1)
{
    setIcon(QIcon(":/rss.png"));
    createContextMenu();

    networkXmlAccess = new QNetworkAccessManager(this);
    networkIconAccess = new QNetworkAccessManager(this);

    connect(networkXmlAccess, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(readXml(QNetworkReply*)));
    connect(networkIconAccess, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(readIcon(QNetworkReply*)));
    QTimer::singleShot(0, this, SLOT(requestXml()));
}

void WeatherTrayIcon::requestXml()
{
    QString url = QString("https://tianqiapi.com/api.php?version=v6&city=%1").arg(city);
    QNetworkRequest request(url);
    request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");

    networkXmlAccess->get(request);
}

void WeatherTrayIcon::readXml(QNetworkReply *reply)
{
    if(reply->error() != QNetworkReply::NoError){
        setToolTip(QString("获取天气失败 %1").arg(reply->errorString()));
        QTimer::singleShot(retryDelaySec * 1000, this, SLOT(requestXml()));
        retryDelaySec <<= 1;
        if(retryDelaySec > 60 * 60)
            retryDelaySec = 1;
        return;
    }
    retryDelaySec = 1;
    QString data = QString(reply->readAll());

    if(!data.isEmpty()){
        populateToolTip(data);
    }

    QTimer::singleShot(60 * 60 * 1000, this, SLOT(requestXml()));
}

void WeatherTrayIcon::readIcon(QNetworkReply *reply)
{
    QUrl redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
    if(redirect.isValid()){
        qInfo() << "redirect";
        QNetworkRequest request(redirect);
        request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");

        networkIconAccess->get(request);
    }
    else{
        QByteArray ba(reply->readAll());
        QPixmap pixmap;
        if(pixmap.loadFromData(ba)){
            QIcon* icon = new QIcon(pixmap);
            setIcon(*icon);
            iconCache.insert(reply->request().url(), icon);
        }
    }
}

void WeatherTrayIcon::setCity(QAction *action)
{
    city = action->data().toString();
    QSettings settings;
    settings.setValue("city", city);
    requestXml();
}

void WeatherTrayIcon::createContextMenu()
{
    QStringList citys;
    citys << "北京" << "大连"  << "上海";

    QSettings settings;
    city = settings.value("city", QVariant(citys.at(0))).toString();

    QActionGroup* group = new QActionGroup(this);
    foreach (const QString &acity, citys) {
        QAction* action = menu.addAction(acity);
        group->addAction(action);
        action->setCheckable(true);
        action->setChecked(acity == city);
        action->setData(acity);
    }
    connect(group, SIGNAL(triggered(QAction*)),
            this, SLOT(setCity(QAction*)));

    menu.addSeparator();
    menu.addAction(QIcon(":/exit.png"), tr("E&xit"), qApp, SLOT(quit()));

    setContextMenu(&menu);
}

void WeatherTrayIcon::populateToolTip(QString data)
{
    QString toolTipText = QString("<font color=\"darkblue\">%1</font><br>")
            .arg(city);

    // parse weather
    QString weather = textForTag("weather", data);
    if(!weather.isEmpty())
    {
        toolTipText += toolTipField("天气", "green", weather);
    }

    QString iconUrl = textForTag("icon", data);

    if(!iconUrl.isEmpty()){
        QUrl url(iconUrl);
        QIcon* icon = iconCache.object(url);
        if(icon && !icon->isNull()){
            setIcon(*icon);
        }
        else{
            QNetworkRequest request(url);
            request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");

            networkIconAccess->get(request);
        }
    }

#ifndef Q_WS_X11
    toolTipText = QTextDocumentFragment::fromHtml(toolTipText).toPlainText();
#endif
    qInfo() << toolTipText;
    setToolTip(toolTipText);
}

QString WeatherTrayIcon::textForTag(QString tag, QString data)
{
    if(tag == "weather"){
        QRegExp rx("<body>.*alt.*<em>(.*)</em>.*wTemp\">(.*)</em>");
        rx.setMinimal(true);
        rx.indexIn(data);
        return rx.cap(1) + " " + rx.cap(2);
    }
    else if(tag == "icon"){
        QRegExp rx("<body>.*src=\"(.*)\"");
        rx.setMinimal(true);
        rx.indexIn(data);
        return rx.cap(1);
    }
    return "";
}

QString WeatherTrayIcon::toolTipField(const QString &name, const QString &color, const QString &value, bool appendBr)
{
    return QString("<i>%1:</i>&nbsp;<font color=\"%2\">%3</font>%4")
            .arg(name).arg(color).arg(value)
            .arg(appendBr ? "<br>" : "");
}
